package cn.fuxi2022.gateway.exception;

import com.alibaba.fastjson.JSON;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.annotation.Primary;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.HashMap;

@Primary // 如果出现多个同类型的Bean，不知道加载哪个，那么加载当前的Bean
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)  // 当前组件优先级最高
public class GatewayExceptionHandler implements ErrorWebExceptionHandler {

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {

        ServerHttpRequest request = exchange.getRequest();
        // 获取当前请求ID
        String requestId = request.getId();
        // 获取报错信息
        String message = ex.getMessage();

        // 构建错误响应
        // 不使用通用处理类，使用将导致依赖冲突问题，自行构建响应
        HashMap<String, Object> map = new HashMap<>();
        map.put("msg", "网关异常，你的请求是非法的");
        map.put("code", 500);
        map.put("requestId", requestId);
        map.put("message", message);

        return Mono.defer(() -> {
            // 把对象转成JSON
            byte[] bytes = JSON.toJSONBytes(map);
            // 获取响应对象
            ServerHttpResponse response = exchange.getResponse();
            // 响应响应类型
            response.getHeaders().add("Content-Type", MediaType.APPLICATION_JSON_VALUE);
            // 设置HTTP响应码
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            DataBuffer buffer = response.bufferFactory().wrap(bytes);
            return response.writeWith(Flux.just(buffer));
        });
    }
}